<template>
    <div class="page">
        <div id="3dcanvs"></div>
        <div class="btn" @click="animateCamera({ x: 0, y: 0, z: 0 }, { x: 100, y: 0, z: 10 })">卧室</div>
        <div class="btn" @click="animateCamera({ x: 0, y: 0, z: 0 }, { x: 200, y: 0, z: 10 })">客厅</div>
        <div v-for="(point, index) in roorms[0].interactivePoints" :key="index" :class="[`point-${point.key}`]">
            <p class="p1">{{ point.value }}</p>
        </div>
    </div>
</template>
  
<script setup>
import { nextTick, onMounted, reactive } from 'vue'
import * as THREE from 'three';
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
// 引入tween动画库
import * as TWEEN from '@tweenjs/tween.js'

let roorms = reactive([
    {
        name: '客厅',
        interactivePoints: [
            {
                key: 'tv',
                value: '电视',
                cover: "img/bg.png",
                position: new THREE.Vector3(-8, 2, -15),
            },
            {
                key: 'art',
                value: '艺术品',
                cover: "img/bg2.png",
                position: new THREE.Vector3(10.5, 0, -15),
            },
        ]
    }
])
//设置场景宽高
const size = {
    width: window.innerWidth,
    height: window.innerHeight
}
//场景
const scene = new THREE.Scene();
//相机
const camera = new THREE.PerspectiveCamera(75, size.width / size.height, 0.1, 1000);
camera.position.set(10, 0, 0)
scene.add(camera);
//渲染器
const renderer = new THREE.WebGLRenderer();
renderer.setSize(size.width, size.height);
renderer.setClearColor(0x000000, 1); //设置背景颜色
renderer.setPixelRatio(window.devicePixelRatio); //设置 canvas 的像素比为当前设备的屏幕像素比，避免高分屏下出现模糊情况。



//创建多个房间以及环境贴图
//创建球体
let arr = ['img/bg.png', 'img/bg2.png', 'img/bg.png']
for (let i = 0; i < 3; i++) {
    const sphereGeometry = new THREE.SphereGeometry(50, 50, 50);
    const textureLoader = new THREE.TextureLoader();
    const sphereMaterial = new THREE.MeshBasicMaterial({
        map: textureLoader.load(arr[i]),
        side: THREE.DoubleSide,
    });
    const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
    sphere.name = `sphere${i}`
    sphere.position.set(0 + i * 100, 0, 0);
    sphere.geometry.scale(1, 1, -1);
    scene.add(sphere);
}

//设置相机移动漫游
//限制缩放

let controls = new OrbitControls(camera, renderer.domElement);
// 转动惯性（阻尼）
controls.enableDamping = true;
controls.dampingFactor = 0.1;
//设置缩放
controls.maxDistance = 5;

// const dir = new THREE.Vector3();
// // 获取相机的视线方向
// camera.getWorldDirection(dir);
//归一化后的向量 相当于 相机的位置减去相机的目标位置(position-lookAt)再进行归一化normalize() 

function animateCamera(position, target) {
    let tween = new TWEEN.Tween({
        px: camera.position.x, // 起始相机位置x
        py: camera.position.y, // 起始相机位置y
        pz: camera.position.z, // 起始相机位置z
        tx: controls.target.x, // 控制点的中心点x 起始目标位置x
        ty: controls.target.y, // 控制点的中心点y 起始目标位置y
        tz: controls.target.z // 控制点的中心点z 起始目标位置z
    })
    tween.to({
        px: position.x,
        py: position.y,
        pz: position.z,
        tx: 100,
        ty: 100,
        tz: 100
    }, 500)
    tween.to({
        px: 100,
        py: 100,
        pz: 100,
        tx: target.x,
        ty: target.y,
        tz: target.z
    }, 1000)
    tween.onUpdate(function () {
        camera.position.x = this._object.px
        camera.position.y = this._object.py
        camera.position.z = this._object.pz
        controls.target.x = this._object.tx
        controls.target.y = this._object.ty
        controls.target.z = this._object.tz
        controls.update()
    })
    tween.easing(TWEEN.Easing.Cubic.InOut)
    tween.start()
}

// 页面缩放事件监听
window.addEventListener("resize", () => {
    size.width = window.innerWidth;
    size.height = window.innerHeight;
    // 更新渲染
    renderer.setSize(size.width, size.height);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    // 更新相机
    camera.aspect = size.width / size.height;
    camera.updateProjectionMatrix();
});

// 渲染函数 
function render() {
    controls && controls.update();
    TWEEN && TWEEN.update();
    renderer.render(scene, camera); //执行渲染操作
    requestAnimationFrame(render);//请求再次执行渲染函数render，渲染下一帧
}
render();

async function increment() {
    await nextTick()
    // DOM 此时已经更新
    document.getElementById("3dcanvs").appendChild(renderer.domElement);
}
onMounted(() => {
    increment()
})

</script>
  
<style lang="scss" scoped>
.page {

    & .btn {
        position: fixed;
        z-index: 100;
        right: 20px;
        top: 200px;
        background-color: #fff;
        font-size: 20px;
        border-radius: 10px;
        padding: 10px 20px;
        cursor: pointer;
    }

    & .btn:nth-of-type(2) {
        top: 300px;
    }

    & .point-tv {
        width: 200px;
    }
}
</style>
  